#ifndef NTREEVIEW_H
#define NTREEVIEW_H

#include <QTreeView>
#include <QWidget>
#include "NCore/GY_NPage.h"
#include "GY_ControlLibrary_global.h"
#include "NCore/GY_NStyle.h"
#include <QStandardItemModel>
#include <QVariant>
#include "GY_WidgetReflect.h"
#include "GY_NAbstractItemWidget.h"
#include <QDebug>

class GY_CONTROLLIBRARY_EXPORT GY_NTreeView : public QTreeView , public GY_NStyle
{
    Q_OBJECT

signals:
    void clickedCustomWidged(const QVariant &id,const qint32 columenIndex,const QVariant &data);

public:
    explicit GY_NTreeView(QWidget *parent = nullptr);
    /**
     * @brief setHorizontalHeaderLabels 设置表头
     * @param list
     */
    void setHorizontalHeaderLabels(const QStringList &list);
    /**
     * @brief setColumnCount 设置列数
     * @param value 值
     */
    void setColumnCount(int value);
    /**
     * @brief addColumnName 添加列
     * @param name 列名称
     */
    void addColumnName(const QString &name);
    template<typename T>
    void addColumnNameAndRegisterControl(const QString &name);
    template<typename T>
    bool registerControl(qint32 columnIndex);
    /**
     * @brief setHasCheckBox 设置是否将第一列设置成复选框,
     * @param value
     */
    void setHasCheckBox(bool value);
    /**
     * @brief getCheckStateAtRow 获取某行的选中状态
     * @param row
     * @param parent
     * @return
     */
    bool getCheckStateAtRow(int row, const QModelIndex &parent = QModelIndex());
    bool getCheckStateByItem(QStandardItem *item);
    /**
     * @brief setRowCheckState 设置某行的选中状状态
     * @param row
     * @param isChecked
     * @param parent
     */
    void setRowCheckState(int row, bool isChecked, const QModelIndex &parent = QModelIndex());
    /**
     * @brief deleteRowByIndex 删除目标行
     * @param row
     * @param parent
     */
    void deleteRowByIndex(int row, const QModelIndex &parent = QModelIndex());
    /**
     * @brief deleteRowById 根据Id删除行
     * @param id
     */
    void deleteRowById(const QVariant& id);
    /**
     * @brief deleteCheckedRow 删除选中行
     * @param pItem
     */
    void deleteCheckedRow(QStandardItem *pItem = nullptr);
    /**
     * @brief getCheckedDatas 获取选中的数据
     * @param list
     * @param pItem
     */
    void getCheckedDatas(QList<QList<QVariant>> &list, QStandardItem *pItem = nullptr);
    /**
     * @brief getCheckedDataIds 获取当前选选择行ID
     * @param idList
     * @param pItem
     */
    void getCheckedDataIds(QVector<QVariant> &idList, QStandardItem *pItem= nullptr);
    /**
     * @brief getDataById 通过id获取数据
     * @param id
     * @return
     */
    QList<QVariant> getDataById(const QVariant &id);
    /**
     * @brief updateDataById 通过id更新数据
     * @param id
     * @param list
     * @param isChecked
     */
    void updateDataById(const QVariant &id, const QList<QVariant> &list, bool isChecked = false);
    /**
     * @brief addRowData 插入一行数据，需要传入父 index, 如果不传则为顶级节点
     * @param list
     * @param id
     * @param parent
     * @return
     */
    QModelIndex addRowData(const QList<QVariant> &list, const QVariant &id = -1 ,const QModelIndex &parent = QModelIndex());
    /**
     * @brief getModelIndexById 获取某id所在行的 QModelIndex
     * @param id
     * @param parent
     * @return
     */
    QModelIndex getModelIndexById(const QVariant &id, const QModelIndex &parent = QModelIndex());
    /**
     * @brief getItemId 获取Itemid
     * @param item
     * @return
     */
    QVariant getItemId(const QStandardItem *item);
    /**
     * @brief removeAllData 删除所有数据
     */
    void removeAllData();
    /**
     * @brief getCurrentSelectId 获取当前选中行
     * @return
     */
    QVariant getCurrentSelectId();
    QStandardItemModel *getModel();

private:
    //!注册控件信息
    QMap<qint32,QString> m_RegisterInfo;
    //!表格model
    QStandardItemModel* m_model;
    //!是否在将第一列设置成复选框
    bool m_hasCheckBox =  false;
    //!数据角色
    const static int m_dataRole;
    //!Id角色
    const static int m_IdRole;
    //!存放注册类型构造函数
    QHash<QString,WidgetReflect::Constructor> m_RegisterHash;
};

/**
 *registerControl 注册控件
 */
template<typename T>
bool GY_NTreeView::registerControl(qint32 columnIndex)
{
    if(columnIndex>=m_model->columnCount())
    {
        return false;
    }
    WidgetReflect::Constructor pFun=WidgetReflect::registerClass<T>();
    if(m_RegisterInfo.contains(columnIndex))
    {
        m_RegisterInfo.remove(columnIndex);
    }
    QString className = QString(T::staticMetaObject.className());
    m_RegisterInfo.insert(columnIndex, className);
    m_RegisterHash.insert(className,pFun);
    return true;
}
template<typename T>
void GY_NTreeView::addColumnNameAndRegisterControl(const QString &name)
{
    QStandardItem *item = new QStandardItem;
    item->setText(name);
    item->setTextAlignment(Qt::AlignCenter);
    int i = m_model->columnCount();
    m_model->setHorizontalHeaderItem(i, item);
    registerControl<T>(i);
}

#endif // NTREEVIEW_H
